package com.czk.polling;

import com.czk.ServerIps;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 平滑权重轮询算法
 *
 * @Author:ChenZhangKun
 * @Date: 2021/4/22 15:44
 */
public class SmoothWeightRobin {
    private static Map<String, Weight> weightMap = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(getServer_1());
        }
    }

    /**
     * 拿到服务器
     *
     * @return
     */
    public static String getServer() {
        // 计算权重和
        int totalWeight = 0;
        for (Integer value : ServerIps.WEIGHT_LIST.values()) {
            totalWeight += value;
        }
        if (weightMap.isEmpty()) {
            // 初始化
            ServerIps.WEIGHT_LIST.forEach((key, value) -> {
                // 放入集合
                weightMap.put(key, new Weight(key, value, 0));
            });
        }
        // 循环
        for (Weight weight : weightMap.values()) {
            // 加当前值
            weight.setCurrentWeight(weight.getCurrentWeight() + weight.getWeight());
        }
        //
        Weight maxCurrentWeight = null;
        for (Weight weight : weightMap.values()) {
            // 拿到最大值
            if (maxCurrentWeight == null || weight.getCurrentWeight() > maxCurrentWeight.getCurrentWeight()) {
                maxCurrentWeight = weight;
            }
        }
        // 减去最大值
        maxCurrentWeight.setCurrentWeight(maxCurrentWeight.getCurrentWeight() - totalWeight);
        return maxCurrentWeight.getIp();
    }

    static int totalValue = 0;

    /**
     * 平滑轮询的练习
     *
     * @return
     */
    public static String getServer_1() {
        // 计算总和
        for (Integer value : ServerIps.WEIGHT_LIST.values()) {
            totalValue += value;
        }
        if (weightMap.isEmpty()) {
            // 初始化
            ServerIps.WEIGHT_LIST.forEach((key, value) -> {
                // 加入map
                weightMap.put(key, new Weight(key, value, 0));
            });
        }
        // 初始化currentWeight
        for (Weight weight : weightMap.values()) {
            weight.setCurrentWeight(weight.getCurrentWeight() + weight.getWeight());
        }
        // 拿到最大的current
        Weight maxCurrent = null;
        for (Weight weight : weightMap.values()) {
            if (maxCurrent == null || weight.getCurrentWeight() > maxCurrent.getCurrentWeight()) {
                maxCurrent = weight;
            }
        }
        // 减去最大值
        maxCurrent.setCurrentWeight(maxCurrent.getCurrentWeight() - totalValue);
        // 拿到ip
        return maxCurrent.getIp();
    }

}

class Weight {
    private String ip;
    private Integer weight;
    private Integer currentWeight;

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public Integer getCurrentWeight() {
        return currentWeight;
    }

    public void setCurrentWeight(Integer currentWeight) {
        this.currentWeight = currentWeight;
    }

    public Weight(String ip, Integer weight, Integer currentWeight) {
        this.ip = ip;
        this.weight = weight;
        this.currentWeight = currentWeight;
    }
}
